<!--  -->
<template>
  <div class="app-container">
    <!-- START 卡片视图 START -->
    <el-card style="height: 80px; margin-bottom: 10px;">
      <!-- START 搜索与添加按扭区域 START -->
      <el-row :gutter="20">
        <el-col :span="8">
          <el-input
            v-model="queryInfo.roleName"
            placeholder="请输入要搜索的角色名"
            clearable
            @clear="getRolesList"
          >
            <el-button
              slot="append"
              icon="el-icon-search"
              @click="getRolesList"
            />
          </el-input>
        </el-col>
        <el-col :span="4">
          <el-button type="primary"  icon="el-icon-circle-plus-outline" @click="openRoleDialog">添加角色</el-button>
        </el-col>
      </el-row>
      <!--  END 搜索与添加按扭区域 END -->
    </el-card>
    <!-- END 卡片视图 END -->

    <!-- START 角色列表区域 START -->
    <el-card>
      <el-table :data="roleList" :stripe="true" v-loading="listLoading" :border="true" style="width: 100%">
<!-- type="expand" 可展开式的箭头，实现点击这个箭头，将当前角色所拥有的权限列表展开 -->
        <el-table-column type="expand">
          <template slot-scope="scope">
 <!-- {{ scope.row }} 得到当前角色对象 -->
            <el-row v-for="(item1, idx1) in scope.row.children" :key="idx1" :class="['border-bottom', idx1 === 0 ? 'border-top' : '','vcenter']">
                <!-- 渲染一级权限 -->
                <el-col :span="5">
                  <el-tag type="primary" effect="dark" closable  @close="removeRoleThreeRight(scope.row, item1.id)">{{item1.name}}</el-tag>
                  <i class="el-icon-caret-right"></i>
                </el-col>
                <!-- 渲染二级和三级权限 -->
                <el-col :span="19">
                  <el-row v-for="(item2, idx2) in item1.children" :key="idx2">
                      <!-- 渲染二级权限 -->
                      <el-col :span="6">
                        <el-tag type="success"  effect="dark" closable  @close="removeRoleThreeRight(scope.row, item2.id)">{{item2.name}}</el-tag>
                        <i class="el-icon-caret-right"></i>
                      </el-col>
                      <!-- 渲染三级权限 -->
                      <el-col :span="18">
                        <el-row v-for="(item3, idx3) in item2.children" :key="idx3">
                            <el-tag type="warning"  effect="dark" closable  @close="removeRoleThreeRight(scope.row, item3.id)">{{item3.name}}</el-tag>
                        </el-row>
                      </el-col>
                  </el-row>
                </el-col>
            </el-row>

          </template>
        </el-table-column>
        <el-table-column label="ID" prop="id" sortable="custom" align="center" width="60">
          <template slot-scope="{row}">
            <span>{{ row.id }}</span>
          </template>
        </el-table-column>
        <el-table-column label="英文名称" width="300px" align="center">
          <template slot-scope="{row}">
            <span>{{ row.name }}</span>
          </template>
        </el-table-column>
        <el-table-column label="中文名称" width="300px" align="center">
          <template slot-scope="{row}">
            <span>{{ row.nameZh }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center">
          <!-- 使用作用域插槽的形式为[角色等级]列自定义内容，使用scope来接收所有的数据 -->
          <template slot-scope="scope">
            <!-- 编辑按扭 -->
            <el-button icon="el-icon-edit" type="primary" size="mini" plain round @click="showEditDialog(scope.row)">编辑</el-button>
            <!-- 删除按扭 -->
            <el-button icon="el-icon-delete" type="danger" plain round size="mini" @click="delRoleById(scope.row)">删除</el-button>
            <!-- 分配权限按扭 -->
            <el-button icon="el-icon-setting" type="success" size="mini" plain round @click="assignRightToRole(scope.row)">分配权限</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- START 分页区 START -->
      <pagination v-show="totalCount>0" :total="totalCount" :page.sync="queryInfo.currPageNo" :limit.sync="queryInfo.pageSize" @pagination="getRolesList" />
      <!-- END 分页区 END -->

    </el-card>
    <!-- END 权限列表区域 END -->
<!-- START 添加角色弹出对话框窗口 START -->
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="400px">
  <el-form ref="dataFormRef" :rules="rules" :model="role" label-position="left" label-width="64px" style="width: 360px; ">
        <el-form-item label="英文名" prop="name">
          <el-input v-model="role.name" placeholder="角色英文名" />
        </el-form-item>
        <el-form-item label="中文名" prop="nameZh">
          <el-input v-model="role.nameZh" placeholder="角色中文名" />
        </el-form-item>
  </el-form>
  <div slot="footer" class="dialog-footer">
    <el-button @click="cancelEvent()">
      取消
    </el-button>
    <el-button type="primary" @click="dialogStatus==='create'?insertData():updateData()">
      确认
    </el-button>
  </div>
</el-dialog>
<!-- END 添加角色弹出对话框窗口 END -->
<!-- START 分配权限 START -->
<el-dialog
      title="分配权限"
      :visible.sync="assignRightVisible"
      width="50%">
      <!-- START 主体内容部分——权限树形控件 START -->
      <!-- :default-expanded-keys="[2, 3]"
        :default-checked-keys="[5]" -->
      <el-tree
        :data="treeRightList"
        show-checkbox
        :default-checked-keys="defaultCheckedKeys"
        node-key="id"
        :props="defaultProps" 
        ref="assignRightRef">
      </el-tree>
      <!-- END 主体内容部分——权限树形控件 END -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="assignRightVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveAssignMenu">确 定</el-button>
      </span>
    </el-dialog>
    <!-- END 分配权限 END -->

  </div>
</template>

<script>
// 这里可以导入其他文件（比如：组件，工具js，第三方插件js，json文件，图片文件等等）
// 例如：import 《组件名称》 from '《组件路径》';
// 从 /api/role.js中解构出 pageRoleList方法，在当前组件中导入
import { pageRoleList,saveRole,findByRoleId,updateRole,delRoleByRoleId,assignMenu,delMenuByRoleId } from '@/api/role'
import { getAllMenuList,getMenuIdsByRoleId } from '@/api/menu'
// 导入分页公共组件
import Pagination from '@/components/Pagination'
export default {
// import引入的组件需要注入到对象中才能使用
  components: {
    // 在当前组件中进行注册
    Pagination
  },
  // props实现父子组件传递数据
  props: {},
  data() {
    // 这里存放数据
    return {
      // 查询条件
      queryInfo: {
        roleName: '', // 角色名
        currPageNo: 1, // 当前页码
        pageSize: 4// 每页显示5条数据
      },
      // 角色列表
      roleList: [],
      // 用来保存分页时所需要的总记录数
      totalCount: 0, // 当发送异步请求用户列表数据时设置它为true,可出现正在加载中
      listLoading: true,

      // 用于控制添加/修改角色对话框的显示和隐藏
      dialogFormVisible: false,
      // 因为添加和编辑用户共用一个弹出窗口，通过dialogStatus来动态设置弹出窗口的标题。
      dialogStatus: '',
      textMap: {
        create: '添加角色',
        update: '编辑角色'
      },
      // 用于绑定[添加/编辑角色对话框]里的表单数据
      role: {
        id: undefined, // 角色ID
        name: '', // 角色的英文名
        nameZh: '' // 角色的中文名
      },
      // 添加表单验证规则对象
      rules: {
        name: [
          { required: true, message: '角色英文名必填', trigger: 'blur' },
          { min: 2, max: 30, message: '姓名的长度在2~30个字符之间', trigger: 'blur' }
        ],
        nameZh: [
          { required: true, message: '角色中文名必填', trigger: 'blur' },
          { min: 2, max: 15, message: '姓名的长度在2~15个字符之间', trigger: 'blur' }
        ] 
      },
       // 用于绑定分配权限对话框中树状权限的数据源
       treeRightList: [],
      // 控制[分配权限对话框]的显示与隐藏
      assignRightVisible: false,
      defaultProps: {
         // children作为子节点
        children: 'children',
        // 以菜单名称作为显示文本值
        label: 'name'
      },
      //角色编号
      rid:0,
      //默认选中的权限
      defaultCheckedKeys:[]


    }
  },
  // 生命周期 - 挂载完成（可以访问DOM元素）
  mounted() {
    this.getRolesList()
  },
  // 方法集合
  methods: {
    // 添加角色按扭的点击事件
    openRoleDialog() { 
      this.dialogFormVisible = true

      this.dialogStatus="create"

      this.resetRole();
    },
    // 按角色的英文名或中文名模糊查询角色的分页列表信息
    getRolesList() {
      // true时，表格中就会出现正在加载图标
      this.listLoading = true
      pageRoleList(this.queryInfo).then((res) => {
        // false时，正在加载图标就会消失
        this.listLoading = false
        this.roleList = res.data.list
        // 获取总记录数
        this.totalCount = res.data.totalCount
      }).catch((err) => {
        console.log(err)
      })
    },
    // 重置Role对象
    resetRole() {
        this.role = {
          id: undefined,
          name: '',
          nameZh: '' 
        }
    },
    cancelEvent(){
      //1.关闭模态框
      this.dialogFormVisible = false
    },
    insertData(){
      this.$refs['dataFormRef'].validate((valid) => {
        if(valid){
          saveRole(this.role)
            .then((res)=>{
              //1.关闭模态框
              this.dialogFormVisible = false
              if(res.code==200){
                //2.给出友好提示
                this.$message({
                  title: '提示',
                  message: res.message,
                  type: 'success',
                  duration: 2000
                });
                //3.刷新列表
                this.getRolesList()
              }else{
                //2.给出友好提示
                this.$message({
                  title: '提示',
                  message: res.message,
                  type: 'error',
                  duration: 2000
                })
              }
            })
            .catch((err)=>{
              console.log(err);
            })
        }
      });
    },
    showEditDialog(row){
        //1.打开模态框
        this.dialogFormVisible = true
        //2.设置标题
        this.dialogStatus="update"
        //3.重置表单项
        this.resetRole()

        //4.数据回显
        findByRoleId(row.id)
        .then((res)=>{
          this.role = res
        })
        .catch((err)=>{
          console.log(err);
        })
    },
    updateData(){
        //1.表单验证
        this.$refs['dataFormRef'].validate((valid) => {
          if(valid){
            updateRole(this.role)
            .then((res)=>{
                 //1.关闭模态框
                 this.dialogFormVisible=false
                if(res.code==200){
                    //2.友好提示
                    this.$message.success(res.message)

                    //3.刷新数据
                    this.getRolesList();
                }else{
                    //2.友好提示
                    this.$message.error(res.message)
                }
            }).catch((err)=>{
              console.log(err);
            });
          }
        })
    },
    delRoleById(role){
      this.$confirm('确认要删除此角色信息吗?', {
            confirmButtonText: '确认',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            delRoleByRoleId(role.id).then((res) => {
              if(res.code==200){
                //1.友好提示
                this.$message.success(res.message)
                //2.刷新列表
                this.getRolesList();
              }else{
                 //1.友好提示
                 this.$message.error(res.message)
              }
            }).catch((err) => {
              console.log(err);
            })
          }).catch(() => {
            this.$message('您取消了删除！')
          })
      },

      assignRightToRole(row){
        //1.显示分配权限的模态框
        this.assignRightVisible=true
        //2.发送ajax获取所有的权限
        getAllMenuList().then((res)=>{
            this.treeRightList=res;
        }).catch((err)=>{
          console.log(err)
        })
        //3.给rid数据模型赋值
        this.rid=row.id;
        
        //4.清空选中的权限
        this.$nextTick(function() {
          // DOM更新完毕会才会执行this.$nextTick函数
          this.$refs['assignRightRef'].setCheckedKeys([])
        })
        //5.发送ajax请求
        getMenuIdsByRoleId(row.id).then((res) => {
          let intArr = [] // 用来保存权限id集合在分割成字符串数组并转换成整型后的数组
          if (res !== null) {
            const strArr = res.split(',') // 分割成字符串数组
            // 将字符串数组转换成整型数组
            intArr = strArr.map(item => {
              return +item
            })
          }
          this.defaultCheckedKeys=res!=null?intArr:[];
          const newArr = [] // 用来保存被勾选的权限id数组(即第三层权限id数组)
          if (this.defaultCheckedKeys && this.defaultCheckedKeys.length !== 0) {
            // 对defaultCheckedKeys默认勾选权限id数组进行遍历
            this.defaultCheckedKeys.forEach(item => {
              this.checked(item, this.treeRightList, newArr)
            })
            this.defaultCheckedKeys = newArr
          }
        });
      },
      //保存权限分配
      saveAssignMenu(){
        //获取所有选中树节点的值
        const checkedKeys =this.$refs["assignRightRef"].getCheckedKeys();
        const parentKeys = this.$refs["assignRightRef"].getHalfCheckedKeys() // 半选状态的key

        let strArr = checkedKeys.concat(parentKeys).toString(',') // strArr格式为 "2,3"
        let mid = []
        if (strArr !== null) {
          strArr = strArr.split(',') // 分割成字符串数组
          // 将字符串数组转换成整型数组
          mid = strArr.map(item => {
            return +item
          })
        }

        //发送ajax请求
        const param = { 'rid': this.rid, 'mid': mid }
        assignMenu(param).then((res) => {
            if(res.code==200){
              //友好提示
              this.$message.success(res.message)
              //刷新
              this.getRolesList()
            }else{
               //友好提示
               this.$message.error(res.message)
            }
        }).catch((err) => {
          console.log(err)
          this.$message.error('分配权限出现错误!')
        })

        //关闭模态
        this.assignRightVisible=false;
      },
      checked(id, data, newArr) {
        data.forEach(item => {
          if (item.id === id) {
            // item.children.length === 0 表示item.children没有数据了，即当前节点为最后的子节点
            if (item.children && item.children.length === 0) {
              // 如果当前节点是最后的子节点就把它添加到newArr数组中
              newArr.push(item.id)
            }
          } else {
            // 如果当前节点不是最后一层子节点(可能是第一层或第二层)，那么再调用checked()进行递归
            // 直到当前节点为最后一层子节点，那么就把它加入到newArr数组中
            if (item.children != null && item.children.length !== 0) {
              this.checked(id, item.children, newArr)
            }
          }
        })
      },
      // 根据角色ID删除对应的权限
      // role为角色对象
      // id为当前需要进行删除的权限ID
      removeRoleThreeRight(role, id) {
        this.$confirm(
          '此操作将永久删除该信息，是否继续?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
          const param = { roleId: role.id, menuId: id }
          delMenuByRoleId(param).then((res) => {
            if (res.code === 200) {
              this.$message.success(res.message)
              // 成功后把当前角色最新的权限列表进行返回，之后赋值给角色对象的children，实现异步刷新角色理的权限列表
              role.children = res.data 
            }
          }).catch((err) => {
            this.$message.error('删除权限失败！')
          })
        }).catch(() => {
          return this.$message.info('您取消了删除！')
        })
      }
  }
}
</script>
<style scoped>
  .el-tag{
    margin: 7px;
  }
  .border-top{
    /* 添加上边框线*/
    border-top: 1px solid #eee;
  }
  .border-bottom {
    /* 添加下边框线 */
    border-bottom: 1px solid #eee;
    border-left: 1px solid #eee;
    border-right: 1px solid #eee;
  }
  .vcenter{
    display: flex;
    align-items: center;
  }
</style>
